<?php

namespace app\index\controller;

use app\index\BaseController;
use app\common\services\DependencyCheck;
use app\http\middleware\CheckAuth;
use RuntimeException;
use think\facade\Request;
use think\facade\Route;
use think\Error;
use think\exception\ThrowableError;
use think\facade\App;

class Index extends BaseController
{
    /**
     * 主页面
     *
     * @skip
     */
    public function index()
    {
        $path = env('root_path') . 'public/index.html';
        return file_exists($path) ? file_get_contents($path) : $this->e404();
    }

    /**
     * 检查服务器依赖是否正常
     *
     * @skip
     */
    public function check()
    {
        try {
            $check = new DependencyCheck([
                'OpenSSL' => 'ext_exist:openssl',
                'FileInfo' => 'ext_exist:fileinfo',
                'GD2' => 'ext_exist:gd',
                'MbString' => 'ext_exist:mbstring',
                'MySQLi' => 'ext_exist:mysqli',
                'PDO' => 'ext_exist:pdo_mysql',
                'Filter' => 'ext_exist:filter',
                '密码验证' => 'func_exist:password_verify',
                'ZIP压缩' => 'class_exist:\ZipArchive',
                '私钥' => 'can_read:@/runtime/keys/private',
                '公钥' => 'can_read:@/runtime/keys/public',
                'TPRuntime' => 'can_write:@/runtime/_test.txt',
                '压缩目录' => 'can_write:@/runtime/zip/_test.txt',
                '图像目录' => 'can_write:@/public/uploads/image/_test.txt',
                '头像目录' => 'can_write:@/public/uploads/avatar/_test.txt',
                '数据库连接' => 'db',
            ]);
            if (request()->type() === 'json') {
                return json($check->check());
            } else {
                return self::buildTable($check->check());
            }
        } catch (RuntimeException $e) {
            error($e->getMessage());
        }
    }

    /**
     * 查看服务器版本
     */
    public function version()
    {
        return json([
            'lastest_version' => systeminfo('version.lastest'),
            'min_version' => systeminfo('version.min'),
            'lastest_version_text' => systeminfo('version.lastest_text'),
            'min_version_text' => systeminfo('version.min_text'),
        ]);
    }

    /**
     * 聚合请求
     * @skip
     */
    public function mixedRequests()
    {
        $items = input();
        if (!is_array($items)) {
            error('聚合请求必须是任务数组', 422);
        }
        $result = [];
        foreach ($items as $name => $item) {
            // 检查URL是否存在
            if (!isset($item['url'])) {
                $result[$name] = [
                    'executed' => false,
                ];
                continue;
            }
            // 检查条件是否满足
            if (isset($item['condition']) && !$this->checkCondition($item['condition'])) {
                $result[$name] = [
                    'executed' => false,
                ];
                continue;
            }
            // 模拟请求
            $url = $item['url'];
            $method = isset($item['method']) ? $item['method'] : 'GET';
            $data = isset($item['data']) ? $item['data'] : [];
            $response = $this->simulateRequest($method, $url, $data);
            // 返回结果
            $result[$name] = [
                'executed' => true,
                'status' => $response->getCode(),
                'data' => $response->getData()
            ];
        }
        return json($result);
    }

    protected function checkCondition($condition)
    {
        $name = array_shift($condition);
        $result = null;
        switch ($name) {
            case 'login':
                $user = getCurrentUser();
                return $user !== null;
                break;
            case 'can':
                /** @var CheckAuth $check */
                $check = app(CheckAuth::class);
                [$permission] = $condition;
                return $check->can($permission);
                break;
            case 'modified':
                [$key, $clientTime] = $condition;
                $serverTime = systeminfo($key);
                return $serverTime > $clientTime;
                break;
            default:
                $result = true;
                break;
        }
        return $result;
    }

    /**
     * 模拟请求
     */
    public function simulateRequest($method, $uri, $parameters = [], $cookies = [], $files = [], $server = [])
    {
        $server = array_replace($server, [
            'HTTP_ACCEPT' => 'application/json'
        ]); // 强制返回json
        $request = Request::create(
            $uri, $method, $parameters,
            $cookies, $files, $server
        );
        try {
            Route::setRequest($request);
            $response = App::bindTo('request', $request)->run();
        } catch (\Exception $e) {
            $response = Error::getExceptionHandler()->render($e);
        } catch (\Throwable $e) {
            $response = Error::getExceptionHandler()->render(new ThrowableError($e));
        }
        return $response;
    }

    /**
     * @skip
     */
    public function e413()
    {
        error('上传的文件太大了，换一个小一点的试试？', 413);
    }

    /**
     * @skip
     */
    public function e404()
    {
        error('404 Not Found', 404);
    }

    public static function buildTable($arr)
    {
        $html = '<table>';
        foreach ($arr as $item) {
            $html .= '<tr>';
            $html .= '<td>' . $item['name'] . '</td>';
            $html .= '<td style="background-color: ' . ($item['result'] ? '#67C23A' : '#F56C6C') . ' ">'
                . ($item['result'] ? '通过' : '失败') . '</td>';
            $html .= '</tr>';
        }
        $html .= '</table>';
        return $html;
    }
}
